const { User } = require("../../models");
const { success, failure } = require("../../utils/responses");
const {
  NotFoundError,
  BadRequestError,
  UnauthorizedError,
} = require("../../utils/errors");
const { Op } = require("sequelize");
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");
const moment = require("moment");

/**
 * 登录
 * @param req
 * @param res
 */
exports.login = async (req, res) => {
  const currentDate = moment();
  const futureDate = currentDate.add(30, "days");
  try {
    const { login, password } = req.body;
    if (!login) {
      throw new BadRequestError("邮箱/用户名必须填写.");
    }
    if (!password) {
      throw new BadRequestError("秘密必须填写.");
    }
    // 查询条件
    const condition = {
      where: {
        [Op.or]: [{ email: login }, { username: login }],
      },
    };
    // 通过email 或 username,查询用户是否存在
    const user = await User.findOne(condition);
    if (!user) {
      throw new NotFoundError("用户不存在,无法登录.");
    }
    // 验证密码是否相等
    const isPasswordValid = bcrypt.compareSync(password, user.password);
    if (!isPasswordValid) {
      throw new UnauthorizedError("密码错误.");
    }
    // 生成身份验证令牌
    const token = jwt.sign(
      {
        userId: user.id,
      },
      process.env.TOKEN_SECRET,
      { expiresIn: process.env.TOKEN_EXPIRES },
    );
    success(res, "登录成功", {
      id: user.id,
      username: user.username,
      nickname: user.nickname,
      avatar: user.avatar,
      // 一个用户可能有多个角色
      roles: JSON.parse(user.roles || "[]"),
      accessToken: token,
      token,
      refreshToken: token,
      expires: futureDate,
    });
  } catch (error) {
    failure(res, error);
  }
};

/**
 * 刷新token
 * @param req
 * @param res
 */
exports.refreshToken = async (req, res) => {
  try {
    const currentDate = moment();
    const futureDate = currentDate.add(30, "days");
    const refreshToken = req.body.refreshToken;
    if (!req.body.refreshToken) {
      throw new UnauthorizedError("参数错误.");
    }
    // 验证 token 是否正确
    const decoded = jwt.verify(refreshToken, process.env.TOKEN_SECRET);
    // 解析存入的userId
    const { userId } = decoded;
    const user = await User.findByPk(userId);

    if (!user) {
      throw new UnauthorizedError("用户不存在.");
    }

    // 生成身份验证令牌
    const token = jwt.sign(
      {
        userId,
      },
      process.env.TOKEN_SECRET,
      { expiresIn: process.env.TOKEN_EXPIRES },
    );
    success(res, "登录成功", {
      id: user.id,
      accessToken: token,
      token,
      refreshToken: token,
      expires: futureDate,
    });
  } catch (error) {
    failure(res, error);
  }
};
